init('GenericDataService');
(function(){
	var Collections = require('Collections'),
	    logFactory  = require('Log'),
	    chain       = require('./CommandChain');
	
	var List    = Collections.List,
	    iterate = Collections.iterate,
	    toArray = Collections.toArray;

	var GenericDataService = function(db, entityFactory){
		this.db = db;
		this.log = logFactory.create(db.collectionName);
		this.entityFactory = entityFactory;
		if( typeof entityFactory === 'function' )
			this.toEntity = entityFactory || this.toEntity;
	};
	
	GenericDataService.prototype = {
		toEntity : function(obj, callback){
			if(this.entityFactory)
				this.entityFactory.create(obj, callback);
			else
				throw 'No GenericDataService.toEntity() defined. ' + this;
		},
		_convertResults : function(results, onDone){
			if(!results){
				onDone();
				return;
			}
			var service = this;
			var items = [];
			var cmds = chain.create();
			var appendItem = function(item){ 
				items.push(item)
				cmds.proceed();
			};
			iterate(results, function(result){
				cmds.add(this.toEntity, [result, appendItem], service);
			}, service);
			cmds.execute(function(){
				onDone(items);
			});
		},
		findById : function(id, onLoad, onFail){
			var scope = this;
			onError = onError || onLoad;
			var onSuccess = function(obj){
				if( obj.length == 1 ){
					if( onLoad ) 
						scope.toEntity(obj[0], onLoad);
				}else{
					scope.log.warn("Failed to load record : id=${id}",{id:id});
				}
			};
			var onError = function(err){
				if( onFail ) onFail(null);
			}
			this.db.findById(id, onSuccess, onError);
		},
		findByExample : function(example, onLoad, onFail){
			var service = this;
			var onSuccess = function(obj){
				if( onLoad ) service._convertResults(obj, onLoad);
			};
			var onError = function(err){
				if( onFail ) onFail(null);
			};
			this.db.find({example:example}, onSuccess, onFail);
		},
		list : function(onLoad, onFail){
			var db = this.db;
			var service = this;
			onError = onError || onLoad;
			var onSuccess = function(obj){
				if( onLoad ) service._convertResults(obj, onLoad);
			};
			var onError = function(err){
				if( onFail ) onFail(null);
			};
			db.find({}, onSuccess, onError);
		},
		save : function(obj, onSuccess, onError){
			this.db.save(obj, onSuccess, onError);
		}
	};
	
	exports.constructor = GenericDataService;
})();